[참조]
"화면"을 통해 직접 입출력을 하였지만,
이제부터 "파일"을 통한 입출력을 해보자.
(예시)
f = open('mytext.txt', 'rt') # 또는 f = open('mytext.txt')
strlist = f.readlines()
f.close()
print(strlist)
(해설)
f = open(file,mode='r',encoding=None,...) 으로 파일 객체 f를 만들고, f를 대상으로 멤버함수를 호출한다.mode는 읽기/쓰기/추가(각각 'r', 'w', 'a'), 텍스트 파일/이진수 파일(각각 't','b') 등과 같이 파일 오픈모드를 문자열로 지정한다. 기본값(default)은 읽기('r')와 텍스트 파일('t')이다.
텍스트 파일로 파일을 열면 파일에 입출력은 유니코드 문자열인 str 객체를 통해 수행하게 된다.
이때 텍스트 인코딩(encoding)과 디코딩(decoding)이 발생하게 된다.
이진수 파일로 파일을 열면 파일에 입출력은 bytes 객체를 통해 수행하게 된다.
encoding은 텍스트 파일로 파일을 열때만 의미가 있으며, cp949과 UTF-9 중에 기본 인코딩(즉, None)은 cp949이다.
단지 파일 객체(file object)에 사용되는 주요한 함수는 다음과 같다.
f = open(file,mode='r',encoding=None,...) : 파일 열기
f.name : 파일 이름
f.mode : 파일 열기 모드 조회
f.encoding : 현재 사용되고 있는 인코딩(텍스트 파일에서만 유효)
f.close() : 닫기. 강제로 사용이 끝나 파일을 닫는다. 이를 호출하지 않아도 파일객체가 파괴될 때 파일을 닫는다.
f.flush() : 버퍼 즉시 비우기
f.closed : 파일이 닫혔는지 여부를 True, False로 리턴
f.readable(), f.writable() : 읽거나 쓸 수 있는지 True, False로 리턴
f.seek(offset,whence=SEEK_SET), f.tell() : 파일 포인터 위치 설정. 기준위치 whence에 SEEK_SET(0), SEEK_CUR(1),SEEK_END(2) 지정 가능. offset이 음수이면 기준위치로 부터 역방향으로 위치 지정
f.tell() : 파일 포인터 위치 조회
f.read([size]),f.readline([size]), f.readlines([sizehint]): 읽기 함수
f.write(str), f.writelines(sequenc) : 쓰기 함수
사용이 끝난 파일 객체는 f.close()로 닫고 재사용가능하다.
with 블록을 사용하면 f.close()로 명시적으로 파일을 닫지 않아도 with 블록이 끝날 때 파일 자동으로 닫히게 된다.
(예시) with 블록으로 파일 열기
with open('mytext.txt', 'rt', encoding='utf-8') as f:
strlist = f.readlines()
print(strlist)
보통 텍스트 파일은 read(), readline(), readlines(), write() 등의 함수로 읽고 쓰기를 수행한다.
(예시 1) f.read()로 전체 파일을 읽어오기
f = open('mytext.txt', 'rt', encoding='utf-8')
text = f.read()
f.close()
lines = text.split('\n') # 줄 단위 분리
(예시 2) f.readline()으로 한 줄씩 작업
f = open('mytext.txt', 'rt', encoding='utf-8')
while True:
line = f.readline()
if not line:
break
print(line)
f.close()
(예시 3) f.readlines()으로 모든 라인을 일괄적으로 읽은 후 작업
f = open('mytext.txt', 'rt', encoding='utf-8')
lines = f.readlines()
f.close()
print(lines)
(예시 4) f.write로 파일에 쓰기
f = open('mytextOut.txt', 'wt', encoding='utf-8')
for line in lines:
f.write(line)
f.close()
이스케이프 시퀀스(Escape Sequence):
""" 파이썬 문자열에서 특정한 문자를 나타내기 위해 사용하며,
백슬래쉬(\)로 시작한다."""
\n: 줄 바꿈 문자
\t: 수평 탭 문자
\r: 캐리지 리턴 문자
\\: 백슬래시 문자 그 자체
\': 작은따옴표 문자
\": 큰따옴표 문자
CSV 파일인 경우 Python 빌트인 패키지인 csv 패키지를 사용하면 편리하다.
(예시) 문자열 CSV 읽기
import csv
filename = 'mytext.csv'
f = open(filename, 'rt')
reader = csv.reader(f, delimiter=',')
next(reader) # 헤더 생략
for line in reader:
print(line)
f.close()
위에서 line은 line = [‘first’, ‘second’,’third’] 등과 같이 문자열으로 분리해서 읽힌다.
만약 숫자만을 포함한 CSV 파일이라면 다음과 같이 float()를 통해 변환하면 된다.
(예시) 숫자형 CSV 읽기 (float 변환)
import csv
filename = 'mytext.csv'
f = open(filename, 'rt')
reader = csv.reader(f, delimiter=',')
next(reader) # 헤더 생략
for line in reader:
for word in line:
print(float(word))
f.close()
숫자만 있는 경우(엄밀하게 그럴 필요는 없지만), numpy 이용하는 것이 편리하다.
예를 들어 숫자로 이루어진 테이블 현태의 파일을 쉽게 읽으려면
NumPy의 loadtxt()나 savetxt()를 사용하면 편리하다.
아래는 공백문자로 구분된 테이블 형태의 숫자파일을 읽어들이고 저장한다.
(예시) 공백으로 구분된 숫자파일
import numpy as np
data = np.loadtxt('mytext.txt')
np.savetxt('mytext.out', data, header="# test")
만약 header가 있는 경우 skiprows 인자를 지정할 수 있고,
디폴트로 공백문자인 구분자를 변경하려면 delimiter 인자를 지정한다.
예를 들어 첫번째 줄을 무시하고, 콤머로 구분된 파일을 읽을 때는 다음과 같다.
(예시) CSV 형식, 헤더 스킵 포함
data = np.loadtxt('mytext.csv', skiprows=1, delimiter=',')
이외에도 주석처리, 구분자 변경 등 다양한 사양은 NumPy를 참조한다.
load_txt(), load_csv() 등의 함수는 숫자 데이터가 행렬형태여야 한다.
다음과 같이 정확하게 행렬행태가 아닌 경우에는 직접 파일을 읽어야 한다.
(예시)
PEER NGA STRONG MOTION DATABASE RECORD Loma Prieta, 10/18/1989, Gilroy - Gavilan Coll., UP ACCELERATION TIME SERIES IN UNITS OF G .1922907E-02 .1922299E-02 .1921739E-02 .1921233E-02 .1920794E-02 .1920399E-02 .1920027E-02 .1919639E-02 .1919272E-02 .1919053E-02 .1919245E-02 .1919835E-02 .1920353E-02 .1920558E-02 .1920871E-02 .1921351E-02 .1920903E-02 .1918933E-02 .1916462E-02 .1914326E-02 .1911934E-02 .1910234E-02 .1909185E-02 .1908185E-02 .1914254E-02 .1930378E-02 .1941617E-02 .1933759E-02 .1920388E-02 .1923397E-02 .1926134E-02 .1898869E-02 .1869943E-02 .1879737E-02 .1935748E-02 .2021556E-02 .2070567E-02 .2060695E-02 .2056042E-02 .2081995E-02 .2062717E-02 .1988024E-02
(예시) 직접 파싱하는 사용자 함수
def loadData(file, skiprow=0):
f = open(file, 'rt', encoding='utf-8')
lines = f.readlines()
f.close()
data = []
for i in range(skiprow, len(lines)):
temp = lines[i].split()
for t in temp:
data.append(float(t))
return data